/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import { getModuleIndex, hashFile, TaskDetails } from '@ohos/hvigor';
import { ProjectConfig } from '@ohos/hvigor-arkts-compose';
import fse from 'fs-extra';
import path from 'path';

import { BuildArtifactConst } from '../../const/build-directory-const.js';
import { CommonConst } from '../../const/common-const.js';
import { AbilityTypeEnum } from '../../enum/ability-type-enum.js';
import { CodeType } from '../../enum/code-type-enum.js';
import { LegacyAbilityModel } from '../../model/ability/legacy-ability-model.js';
import { LegacyModuleModelImpl } from '../../model/module/legacy-module-model-impl.js';
import { OhosLogger } from '../../utils/log/ohos-logger.js';
import { mod } from '../../utils/math-util.js';
import { TaskNames } from '../common/task-names.js';
import { TargetTaskService } from '../service/target-task-service.js';
import { submitArkCompileWork } from '../worker/run-ark.js';

import { LegacyCompileNode } from './legacy-compile-node.js';

export class LegacyArkCompile extends LegacyCompileNode {
  constructor(taskService: TargetTaskService, codeType: CodeType, taskDetails: TaskDetails = TaskNames.LegacyFATask.COMPILE_ARK) {
    super(taskService, codeType, taskDetails);
  }

  protected async doTaskAction(): Promise<void> {
    const logger = OhosLogger.getLogger(LegacyArkCompile.name);
    const abilityObjs: LegacyAbilityModel[] = (this.moduleModel as LegacyModuleModelImpl).getLegacyAbilities(this.targetName);
    const rOS = this.sdkInfo.isOhos ? CommonConst.OPEN_HARMONY : CommonConst.HARMONY_OS;
    const sInfo =
      `${this.sdkInfo.isOhos}:${this.sdkInfo.getSdkVersion()}:` + `${this.sdkInfo.getEtsComponentVersion()}:${this.sdkInfo.getEtsComponentReleaseType()}`;
    this.validateAbility(this.log);
    for (let i = 0; i < abilityObjs.length; i++) {
      const abilityInfo: LegacyAbilityModel = abilityObjs[i];
      if (abilityInfo.getSrcLanguage() !== this.codeType) {
        continue;
      }
      const projectConfig: ProjectConfig = this.initDefaultLegacyArkConfig(rOS, sInfo, abilityInfo);
      this.log.debug('build config:');
      this.log.debug(projectConfig);
      let workId: string | null = null;
      workId = await submitArkCompileWork(
        this,
        this.getWorkerPool(),
        logger,
        projectConfig,
        (compileEvents: object[]) => {
          this.moveReleaseMap(this.targetData, logger, `js/${abilityInfo.getRelateSrcPath()}`);
          this.handleCompileEvents(compileEvents, workId ? this.getSubDurationEvent(workId) : this.durationEvent, false);
        },
        this.getWorkerPool().getMaxPoolNum() === 0 ? undefined : [mod(getModuleIndex(projectConfig.modulePath), this.getWorkerPool().getMaxPoolNum())],
      );
    }
    await this.arkCompileTestRunner(rOS, sInfo, logger);
  }

  /**
   * 编译testRunner
   *
   * @param rOS 运行时OS
   * @param sInfo sdk信息
   * @param logger 日志
   */
  private async arkCompileTestRunner(rOS: string, sInfo: string, logger: OhosLogger): Promise<void> {
    const nctr = this.needCompileTestRunner();
    if (!nctr[0]) {
      return;
    }
    const testRunnerPath = nctr[1]!;
    const projectConfig: ProjectConfig = this.initTestRunnerLegacyArkConfig(rOS, sInfo, testRunnerPath);
    let workId: string | null = null;
    workId = await submitArkCompileWork(
      this,
      this.getWorkerPool(),
      logger,
      projectConfig,
      (compileEvents: object[]) => this.handleCompileEvents(compileEvents, workId ? this.getSubDurationEvent(workId) : this.durationEvent, false),
      this.getWorkerPool().getMaxPoolNum() === 0 ? undefined : [mod(getModuleIndex(projectConfig.modulePath), this.getWorkerPool().getMaxPoolNum())],
    );
  }

  private initCommonLegacyArkConfig(rOS: string, sInfo: string): any {
    return {
      ...super.initCommonArkConfig(),
      appResource: this.resourceTablePath,
      rawFileResource: this.rawFileResource,
      resourceTableHash: hashFile(this.resourceTablePath),
      runtimeOS: rOS,
      sdkInfo: sInfo,
      compileMode: this.moduleModel.getProfileOpt().buildOption?.compileMode,
    };
  }

  private initTestRunnerLegacyArkConfig(rOS: string, sInfo: string, testRunnerPath: string): ProjectConfig {
    return {
      ...this.initCommonLegacyArkConfig(rOS, sInfo),
      abilityType: AbilityTypeEnum.TEST_RUNNER,
      aceModuleRoot: path.resolve(this.sourcePath!, testRunnerPath),
      aceModuleBuild: path.resolve(this.aceModuleBuild, testRunnerPath),
      cachePath: this.getLegacyArkCachePath(testRunnerPath),
      supportChunks: false,
    };
  }

  protected initDefaultLegacyArkConfig(rOS: string, sInfo: string, abilityInfo: LegacyAbilityModel): ProjectConfig {
    return {
      ...this.initCommonLegacyArkConfig(rOS, sInfo),
      abilityType: abilityInfo.getType(),
      aceManifestPath: path.resolve(this.manifestDir, abilityInfo.getRelateSrcPath(), BuildArtifactConst.LEGACY_MANIFEST_JSON),
      aceModuleRoot: path.resolve(this.sourcePath!, abilityInfo.getRelateSrcPath()),
      aceModuleBuild: path.resolve(this.aceModuleBuild, abilityInfo.getRelateSrcPath()),
      cachePath: this.getLegacyArkCachePath(abilityInfo.getRelateSrcPath()),
      aceSuperVisualPath: path.resolve(this.aceSuperVisualPath, abilityInfo.getRelateSrcPath()),
      aceBuildJson: path.resolve(this.aceBuildJsonDir, abilityInfo.getRelateSrcPath(), BuildArtifactConst.LOADER_JSON),
      supportChunks: abilityInfo.getType() === AbilityTypeEnum.PAGE,
      sdkPath: this.sdkInfo.sdkDir,
    };
  }

  private getLegacyArkCachePath(abilityCachePath: string): string {
    const cachePath = path.resolve(this.getTaskTempDir(this.targetData), abilityCachePath);
    fse.ensureDirSync(cachePath);
    return cachePath;
  }
}
